from requests import Session
from bs4 import BeautifulSoup
import downloader
from pathlib import Path
import json
import re
import translator
import utils
import urllib
import idmapper
import filemapper
import wiki_decoder

session = Session()
session.trust_env = False
session.adapters.DEFAULT_RETRIES = 10
session.headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67"}

# 物品的图标文件的路径
item_path = Path("img/items")
# 现存的图标文件
item_imgs = {file.name for file in item_path.glob("*")}


def get_titles():
    """ 获取所有物品的title """
    titles = []
    url = "https://ark.fandom.com/wiki/Category:items"
    while True:
        print("正在请求:", url)
        resp = session.get(url)
        soup = BeautifulSoup(resp.content, "lxml")
        h2 = soup.find("h2", text='Pages in category "Items"')
        div = h2.find_next_sibling("div", class_="mw-content-ltr")
        titles.extend((a.get("title") for a in div.select("a")))
        a = h2.find_next_sibling("a", text="next page")
        if a is not None:
            url = f"https://ark.fandom.com{a.get('href')}"
        else:
            break
    return titles


def get_imgs(data: dict, update_img: bool) -> list:
    """ 获取物品的图片 """
    imgs = []
    for key, value in data.items():
        if key.startswith("image"):
            img_name = value
            if img_name not in item_imgs or update_img:
                url = filemapper.get_file_src(img_name)
                downloader.add_task(url, item_path/img_name)
                item_imgs.add(img_name)
            imgs.append(img_name)
    if len(imgs)==0:
        return []
    return imgs

def get_spawn_commands(data: dict) -> list:
    """ 获取物品的生成代码 """
    spawn_commands = {}
    for key in data:
        if key.startswith("blueprintpath"):
            name = key.replace("blueprintpath", "").strip()
            if name not in spawn_commands:
                spawn_commands[name] = {"name": name}
            spawn_commands[name]["blueprintId"] = data[key]
        elif key.startswith("gfi"):
            name = key.replace("gfi", "").strip()
            if name not in spawn_commands:
                spawn_commands[name] = {"name": name}
            spawn_commands[name]["entityId"] = data[key]
        elif key.startswith("itemid"):
            name = key.replace("itemid", "").strip()
            if name not in spawn_commands:
                spawn_commands[name] = {"name": name}
            spawn_commands[name]["itemId"] = data[key]
    return list(spawn_commands.values())


def get_crafted_in(data: dict) -> list:
    """ 获取制作物品所需的工具台 """
    if "craftedin" not in data or data["craftedin"] == "":
        return None
    crafted_in = []
    for key, value in data.items():
        if key.startswith("craftedin") and value not in ("Inventory", ""):
            crafted_in.append(idmapper.get_id(value))
    return crafted_in


def get_ingredientses(data: dict) -> list:
    """ 获取物品的制作配方 """
    if "ingredient1" not in data or data["ingredient1"] == "":
        return None
    ingredientses = []
    for i in range(999):
        if i == 0:
            prefix = ""
        else:
            prefix = f"alt{i}"
            if prefix not in data:
                break
        ingredients = {}
        if prefix != "":
            ingredients["name"] = data[prefix]
        else:
            ingredients["name"] = ""
        ingredients["ingredients"] = []
        for j in range(1, 999):
            if f"{prefix}ingredient{j}" not in data or data[f"{prefix}ingredient{j}"] == "":
                break
            ingredient = {
                "itemId": idmapper.get_id(data[f"{prefix}ingredient{j}"]),
                "quantity": data.get(f"{prefix}quantity{j}", 1)
            }
            ingredients["ingredients"].append(ingredient)
        ingredientses.append(ingredients)
    return ingredientses


def get_consumable(data: dict) -> dict:
    consumable = {}
    # 生命值
    if "health" in data and data["health"] != "":
        consumable["health"] = data["health"]
    # 耐力
    if "stamina" in data and data["stamina"] != "":
        consumable["stamina"] = data["stamina"]
    # 食物
    if "food" in data and data["food"] != "":
        consumable["food"] = data["food"]
    # 水
    if "water" in data and data["water"] != "":
        consumable["water"] = data["water"]
    # 眩晕值
    if "torpor" in data and data["torpor"] != "":
        consumable["torpor"] = data["torpor"]

def scrap_one_item(wiki_id, update_img: bool):
    # 保存网页
    # save_page(wiki_id)
    # return []
    #############

    #############
    item_id = idmapper.get_id(wiki_id)
    with open(f"data/pages/{item_id}", "rb") as f:
        content = f.read()
    soup = BeautifulSoup(content, "lxml")
    #############

    div = soup.find("div", class_="infobox-tabber")
    if div is not None:
        div = soup.find("div", typeof="mw:Extension/tabber")
        data_mw = div.get("data-mw")
        data = json.loads(data_mw)
        tabber_text = data["body"]["extsrc"]
        tabber_data = wiki_decoder.decode_tabber_text(tabber_text)
        wiki_data = tabber_data.values()
    else:
        div = soup.find("div", class_="info-framework")
        span = div.find_previous_sibling("span", typeof="mw:Transclusion")
        data_mw = span.get("data-mw")
        data = json.loads(data_mw)
        params = data["parts"][0]["template"]["params"]
        item_data = {}
        for key, value in params.items():
            item_data[key] = value["wt"]
        wiki_data = [item_data]
    item_list = []
    for data in wiki_data:
        # 物品的id
        item_id = idmapper.get_id(wiki_id)
        # 物品的名称
        if "name" in data and data["name"]!="":
            item_name = data["name"]
        else:
            item_name = idmapper.get_title(wiki_id)
        # 如果页面中物品的数据不止一条，则在id后拼接上物品的名称
        if len(wiki_data) > 1:
            item_id = f"{item_id}#{item_name}"
        item = {}
        item["id"] = item_id
        # 物品的名称
        item["name"] = item_name
        item["nameEn"] = item_name
        item["aliases"] = ""
        # 物品的图片
        item["imgs"] = get_imgs(data, update_img)
        # 物品的描述
        item["description"] = data.get("description","")
        # 物品的分类
        if "category" in data and data["category"] != "":
            item["category"] = data["category"]
        else:
            item["category"] = "Other"
        # 物品的类型
        if "type" in data and data["type"] != "":
            item["type"] = data["type"]
        else:
            item["type"] = "Other"
        # 物品是否可精炼
        item["refineable"] = data.get("refineable") == "Yes"
        # 物品是否可研磨
        item["combustible"] = data.get("combustible") == "Yes"
        # 物品的重量
        if "weight" in data and data["weight"]!="":
            item["weight"] = data["weight"]
        # 物品在手机版上的重量
        if "weightmobile" in data and data["weightmobile"] != "":
            item["weightMobile"] = data["weightmobile"]
        # 物品的堆叠数量
        if "stacksize" in data and data["stacksize"] != "":
            item["stackSize"] = data["stacksize"]
        # 物品的手机版上的堆叠数量
        if "stacksizemobile" in data and data["stacksizemobile"] != "":
            item["satckSizeMobile"] = data["stacksizemobile"]
        # 解锁物品所需的等级
        if "requiredlevel" in data and data["requiredlevel"] != "":
            item["requiredLevel"] = data["requiredlevel"]
        # 手机版解锁物品所需的等级
        if "requiredlevelmobile" in data and data["requiredlevelmobile"] != "":
            item["requiredLevelMobile"] = data["requiredlevelmobile"]
        # 解锁物品所需的印痕点数
        if "engrampoints" in data and data["engrampoints"] != "":
            item["engramPoints"] = data["engrampoints"]
        # 手机版解锁物品所需的印痕点数
        if "engrampointsmobile" in data and data["engrampointsmobile"] != "":
            item["engramPointsMobile"] = data["engrampointsmobile"]
        # 物品的制作经验
        if "craftingxp" in data and data["craftingxp"] != "":
            item["craftingXP"] = float(data["craftingxp"])
        # 物品的制作时间
        if "craftingtime" in data and data["craftingtime"] != "":
            item["craftingTime"] = data["craftingtime"]
        # 加入时游戏的版本
        if "addedin" in data and data["addedin"] != "":
            item["addedIn"] = data["addedin"]
        # 物品的生成代码
        item["spawnCommands"] = get_spawn_commands(data)
        # 制作物品所需的工作间
        if "craftedin" in data:
            item["craftedIn"] = get_crafted_in(data)
        # 制作物品所需的材料
        item["ingredientses"] = get_ingredientses(data)
        # 食物物品增加的属性
        item["consumable"] = get_consumable(data)
        item_list.append(item)
    return item_list


def scrap_all_items(translate=True, update_img=False,start=0) -> None:
    """ 爬取所有物品 """
    # 所有物品的title
    # titles = get_titles()
    with open("data/scraper/item-titles.json", "r") as f:
        titles = json.load(f)
    wiki_ids = []
    for title in titles:
        wiki_id = idmapper.get_wiki_id(title)
        if wiki_id not in wiki_ids:
            wiki_ids.append(wiki_id)
    items = {}
    for i in range(start, len(wiki_ids)):
        wiki_id = wiki_ids[i]
        print(f"正在请求第{i}条数据:{wiki_id}")
        item_list = scrap_one_item(wiki_id, update_img)
        for item in item_list:
            items[item["id"]]=item
    # 翻译物品数据
    if translate:
        translator.translate_items(items)
    # 保存数据
    utils.save_data(items, "data/items.json")


def update_translations():
    """ 更新物品的翻译 """
    items = utils.read_data("data/items.json")
    translator.translate_items(items, update_translations=False)
    utils.save_data(items, "data/items.json")


def add_custom_data():
    """ 添加自定义数据 """
    # 载入物品数据
    items = utils.read_data("data/items.json")
    # 载入自定义数据
    custom_data = utils.read_data("custom-data/items.json")
    for item_id in custom_data:
        # 如果物品不存在则直接添加
        if item_id not in items:
            items[item_id] = custom_data[item_id]
            continue
        item = items[item_id]
        data = custom_data[item_id]
        # 添加自定义别名
        if "aliases" in data:
            item["aliases"] = data["aliases"]
    # 保存修改后的物品数据
    utils.save_data(items, "data/items.json")
    import shutil
    for img in Path("custom-data/img/items").glob("*"):
        if img.name not in item_imgs:
            shutil.copy2(img, item_path)
    

